package switchviz.gui.component;
import java.awt.BorderLayout;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import switchviz.core.ResourceManager;
import switchviz.core.mib.MIBXMLFilter;
import switchviz.util.FileOperations;

public class XMLTree extends JPanel
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 5493573461050473126L;
	protected JTree _jtree;
	protected DefaultTreeModel _treemodel;
	protected XMLTreeNode _root;
	protected IXMLFilter _xmlfilter;
	protected static Logger logger = Logger.getLogger(XMLTree.class);
	protected File _xmlfile;
	protected Document _doc;
	
	public void setXML(File xmlfile)
	{
		_xmlfile = xmlfile;
	}
	
	public File getXML()
	{
		return _xmlfile;
	}
	
	public JTree getTree()
	{
		return _jtree;
	}
	
	public DefaultTreeModel getTreeModel()
	{
		return _treemodel;
	}
	
	public void setFilter(IXMLFilter xmlfilter)
	{
		_xmlfilter = xmlfilter;
	}
	
	public XMLTree(File xmlfile, IXMLFilter xmlfilter) throws JDOMException, IOException
	{
		this.setFilter(xmlfilter);
		this.setXML(xmlfile);
		this.initializeTree();
	}
	
	public XMLTree(File xmlfile) throws JDOMException, IOException
	{
		this.setFilter(new MIBXMLFilter());
		this.setXML(xmlfile);
		this.initializeTree();
	}
	
	public void initializeTree() throws JDOMException, IOException
	{
		initializeStructure();
		initializeGUI();
	}
	
	public void addNode(XMLTreeNode childNode, XMLTreeNode parentNode)
	{
		parentNode.getElement().addContent(childNode.getElement());
		_treemodel.insertNodeInto(childNode, parentNode, parentNode.getChildCount());
	}
	
	public void addNode(XMLTreeNode childNode)
	{
		XMLTreeNode parentNode = (XMLTreeNode)_jtree.getLastSelectedPathComponent();
		addNode(childNode, parentNode);
	}
		
	public void removeNode(XMLTreeNode actNode)
	{
		if (actNode.isRoot()) { return; }
		actNode.getElement().getParent().removeContent(actNode.getElement());
		_jtree.setSelectionPath(new TreePath(actNode.getParent()));
		_treemodel.removeNodeFromParent(actNode);
	}
	
	public void removeNode()
	{
		XMLTreeNode actNode = (XMLTreeNode)_jtree.getLastSelectedPathComponent();
		removeNode(actNode);
	}
		
	public void saveXML() throws IOException
	{
		try 
		{
			FileOperations.saveXML(_xmlfile, _doc);
			if (logger.isInfoEnabled())
				logger.info("File " + _xmlfile.getAbsolutePath() + " successfully saved.");
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
			logger.warn("Problems occured saving the File: " + _xmlfile.getAbsolutePath());
		}
	}
	
	public void saveXMLAs(File newfile)
	{
		this.setXML(newfile);
		try 
		{
			FileOperations.saveXML(newfile, _doc);
			if (logger.isInfoEnabled())
				logger.info("File " + newfile.getAbsolutePath() + " successfully saved.");
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
			logger.warn("Problems occured saving the File: " + newfile.getAbsolutePath());
		}
	}
	
	public void openXML(File openfile) throws Exception
	{
		this.setXML(openfile);
		reload();
	}
	
	public void reload() throws Exception
	{
		_treemodel.setRoot(null);
		SAXBuilder parser = new SAXBuilder();
	    _doc = parser.build(_xmlfile); 
		_root = new XMLTreeNode(_xmlfilter.Extract(_doc.getRootElement()),_doc.getRootElement());
		_treemodel.setRoot(_root);
		getTreeStructure(_root, _doc.getRootElement());
		_treemodel.reload(_root);
	}
	
	protected void setLeafNodeIcon(ImageIcon icon)
	{
	    DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
	    renderer.setLeafIcon(icon);
	    this.getTree().setCellRenderer(renderer);
	}
	
	private void initializeStructure() throws JDOMException, IOException
	{
		SAXBuilder parser = new SAXBuilder();
	    _doc = parser.build(_xmlfile); 
	    _root = new XMLTreeNode(_xmlfilter.Extract(_doc.getRootElement()),_doc.getRootElement());
	    _jtree = new JTree(_root);
	    _jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
	    _treemodel = (DefaultTreeModel)_jtree.getModel();
	    getTreeStructure(_root, _doc.getRootElement());
	    if (logger.isDebugEnabled())
	    	logger.debug("Initialized XML config " + _xmlfile);
	}
	
	private void initializeGUI()
	{
		this.setLayout(ResourceManager.getInstance().getBorderLayout());
		_jtree.expandRow(0);
		_jtree.addSelectionRow(0);
	    JScrollPane scrollpane = new JScrollPane(_jtree);
        this.add(scrollpane, BorderLayout.CENTER);
	}
	
	protected void getTreeStructure(XMLTreeNode ninjaTurtleNode, Element domNode)
	{
		XMLTreeNode ninjaApprenticeTurtleNode;
		Element littleDomNode;
		Iterator<?> it = domNode.getChildren().iterator();
		while (it.hasNext())
		{
			littleDomNode = (Element)it.next();
			if(_xmlfilter.checkIgnore(littleDomNode)) { continue; }
			ninjaApprenticeTurtleNode = new XMLTreeNode(_xmlfilter.Extract(littleDomNode),littleDomNode);
			_treemodel.insertNodeInto(ninjaApprenticeTurtleNode,ninjaTurtleNode, ninjaTurtleNode.getChildCount());
			getTreeStructure(ninjaApprenticeTurtleNode, littleDomNode);
		}
	}
}
